﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;

namespace AgileShare.Framework.CamlQueries
{
	/// <summary>
	/// Represents a query in a ListView. Inherits from SPQuery and can be used directly to get items using SPList.GetItems.
	/// </summary>
	/// <example>This example shows one of the possible ways to use the CamlQueryBuilder.</example>
	/// <code>
	/// CamlQueryBuilder camlQueryBuilder = new CamlQueryBuilder();			
	/// 
	/// camlQueryBuilder.AddClause(LogicalJoin.First, "Field1", ComparisonOperator.BeginsWith, "Value1", ValueType.Text);
	/// camlQueryBuilder.AddClause(LogicalJoin.Or, Guid.NewGuid(), ComparisonOperator.Contains, "Value2", ValueType.ContentTypeId);
	/// camlQueryBuilder.AddClause(LogicalJoin.And, "Field3", ComparisonOperator.DateRangesOverlap, "Value3", ValueType.DateTime);
	/// camlQueryBuilder.AddClause(LogicalJoin.Or, Guid.NewGuid(), ComparisonOperator.Eq, "Value 4", ValueType.Text);
	/// 
	/// camlQueryBuilder.AddOrderBy(Guid.NewGuid(), OrderByDirection.Ascending);
	/// camlQueryBuilder.AddOrderBy("Field1", OrderByDirection.Descending);
	/// 
	/// camlQueryBuilder.AddGroupBy("Field1");
	/// camlQueryBuilder.AddGroupBy(Guid.NewGuid());
	/// 	
	/// CamlQuery query = new CamlQuery(camlQueryBuilder);
	/// SPList list = SPContext.Current.Web.GetList("MyList");
	/// list.GetItems(query);
	/// </code>
	public class CamlQuery : SPQuery
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="CamlQuery"/> class.
		/// </summary>
		public CamlQuery()
			: base()
		{
		}

		/// <summary>
		/// Initializes a new instance of the class by using the specified view.
		/// </summary>
		/// <param name="view">An SPView object.</param>
		public CamlQuery(SPView view)
			: base(view)
		{
		}

		/// <summary>
		/// Initializes a new instance of the class by using the specified CamlQueryBuilder.
		/// </summary>
		/// <param name="camlQueryBuilder">A CamlQueryBuilder object.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldsOnly">True to bring only the specified ViewFields, otherwise false.</param>
		public CamlQuery(CamlQueryBuilder camlQueryBuilder, uint? rowLimit = null)
			: base()
		{
			this.Query = camlQueryBuilder.SPQueryString;

			string viewFields = camlQueryBuilder.SPQueryViewFields;
			if (!string.IsNullOrEmpty(viewFields))
			{
				this.ViewFields = viewFields;
				this.ViewFieldsOnly = true;
			}
			if (rowLimit.HasValue)
			{
				this.RowLimit = rowLimit.Value;
			}
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="CamlQuery"/> class.
		/// </summary>
		/// <param name="fieldId">The field id.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldIds">The view field ids.</param>
		public CamlQuery(Guid fieldId, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, uint? rowLimit = null, params Guid[] viewFieldIds) :
			this(new CamlQueryBuilder(fieldId, comparisonOperator, value, valueType, viewFieldIds), rowLimit)
		{			
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="CamlQuery"/> class.
		/// </summary>
		/// <param name="fieldName">Name of the field.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldNames">The view field names.</param>
		public CamlQuery(string fieldName, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, uint? rowLimit = null, params string[] viewFieldNames) :
			this(new CamlQueryBuilder(fieldName, comparisonOperator, value, valueType, viewFieldNames), rowLimit)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="CamlQuery"/> class.
		/// </summary>
		/// <param name="fieldId">The field id.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="orderById">The order by id.</param>
		/// <param name="orderByDirection">The order by direction.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldIds">The view field ids.</param>
		public CamlQuery(Guid fieldId, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, Guid orderById, OrderByDirection orderByDirection, uint? rowLimit = null, params Guid[] viewFieldIds) :
			this(new CamlQueryBuilder(fieldId, comparisonOperator, value, valueType, orderById, orderByDirection, viewFieldIds), rowLimit)
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="CamlQuery"/> class.
		/// </summary>
		/// <param name="fieldName">Name of the field.</param>
		/// <param name="comparisonOperator">The comparison operator.</param>
		/// <param name="value">The value.</param>
		/// <param name="valueType">Type of the value.</param>
		/// <param name="orderByFieldName">Name of the order by field.</param>
		/// <param name="orderByDirection">The order by direction.</param>
		/// <param name="rowLimit">The row limit.</param>
		/// <param name="viewFieldNames">The view field names.</param>
		public CamlQuery(string fieldName, ComparisonOperator comparisonOperator, object value, CamlValueType valueType, string orderByFieldName, OrderByDirection orderByDirection, uint? rowLimit = null, params string[] viewFieldNames) :
			this(new CamlQueryBuilder(fieldName, comparisonOperator, value, valueType, orderByFieldName, orderByDirection, viewFieldNames), rowLimit)
		{
		}

	}
}
